import { ClickModal, FieldTable, mapField, useCall, useFormValue } from '@/components';
import { Button, Form, Input } from 'antd';
import React, { useEffect, useLayoutEffect, useState } from 'react';

const DollarPrefixInput = ({ value = '$', onChange, ...rest }) => {
  const handleChange = useCall((e) => {
    // if (e.nativeEvent.isComposing === true) return;
    let val = e.target.value;
    if (!val.startsWith('$')) val = `$${val}`;
    onChange(val);
  });
  return <Input value={value} onChange={handleChange} {...rest} />;
};

const FormulaTable = ({ value, onChange, onValidate, readOnly }) => {
  const [form] = Form.useForm();
  const list = useFormValue(form, ['list']) ?? [];
  const fields = [
    [
      'name',
      '变量名',
      readOnly ? 'plain' : DollarPrefixInput,
      {
        initialValue: '$',
        rules: [
          {
            trigger: false,
            message: '变量名不能重复',
            validator(r, val) {
              const list = form.getFieldValue('list');
              const nameMapCount = list.reduce((r, i) => {
                r[i.name] ??= 0;
                r[i.name] += 1;
                return r;
              }, {});
              if (nameMapCount[val] > 1) return Promise.reject('变量名不能重复');
              return Promise.resolve();
            },
          },
          {
            trigger: false,
            pattern: /^\$[0-9a-zA-Z]*$/,
            message: '变量名必须以$开头的字母与数字组合',
          },
        ],
      },
    ],
    [
      'formula',
      '公式',
      readOnly ? 'plain' : null,
      {
        rules: [
          /*{ message: '不能使用逗号', pattern: /^[^,]*$/ }*/
        ],
      },
    ],
  ].map(mapField);

  // 将props.value 解析为数组 { name: 变量名, formula: 公式 }
  useEffect(() => {
    if (!value) return form.setFieldsValue({ list: [] });

    let string = value || '';
    // value 是下面这种形式的字符串
    // `seq.map('$var', ...,'$var', ...)`
    if (string) string = string.substring(string.indexOf('(') + 1, string.lastIndexOf(')'));

    let list = string.match(/'\$[0-9a-zA-Z]*',((?!'\$).)*/g) || [];
    list = list.map(
      (row) => row.replace(/([^']),$/, (r, $1) => $1).match(/^'(?<name>\$[0-9a-zA-Z]*)',(?<formula>.*)$/)?.groups,
    );
    list = list.filter(Boolean);

    form.setFieldsValue({ list });
  }, [value]);

  // 将数组拼接为 seq.map
  const handleChange = () => {
    const list = form.getFieldValue('list') || [];

    let nextValue = null;
    if (list.length) {
      nextValue = list
        .reduce((str, { name, formula }) => str + `'${name || ''}',${formula || ''},`, `seq.map(`)
        .replace(/,$/, ')');
    }

    if (nextValue !== value) onChange?.(nextValue);
  };

  useLayoutEffect(() => {
    if (readOnly) return;
    form.validateFields().then(
      () => {
        onValidate?.(false);
        handleChange();
      },
      () => {
        onValidate?.(true);
      },
    );
  }, [list]);

  return (
    <Form component={false} form={form} validateTrigger={false}>
      <FieldTable
        form={form}
        showAddBtn={!readOnly}
        showRemoveBtn={!readOnly}
        name='list'
        fields={fields}
        onAdd={() => ({ formula: '', name: '$' })}
      />
    </Form>
  );
};

const FormulaEditor = ({ value, onChange, readOnly = false, children }) => {
  const [state, setState] = useState(value);
  const [hasErr, setHasErr] = useState(false);

  const content = <FormulaTable value={state} onChange={setState} onValidate={setHasErr} readOnly={readOnly} />;
  const onToggle = useCall((visi) => {
    setState(visi ? value : null);
  });
  const onOK = useCall(() => {
    onChange?.(state);
  });

  const title = readOnly ? '查看公式' : '编辑公式';

  return (
    <ClickModal title={title} content={content} onOk={onOK} onToggle={onToggle} okButtonProps={{ disabled: hasErr }}>
      {children || (
        <Button size='small' type='link'>
          {title}
        </Button>
      )}
    </ClickModal>
  );
};
export default FormulaEditor;
